﻿using System;
using System.ComponentModel.Design;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using EnvDTE;
using EnvDTE80;
using Microsoft.VisualStudio.Shell;
using Microsoft.VisualStudio.Shell.Interop;
using Task = System.Threading.Tasks.Task;

namespace jTCodeGenerate
{
    /// <summary>
    /// Command handler
    /// </summary>
    internal sealed class MainCommand
    {
        /// <summary>
        /// Command ID.
        /// </summary>
        public const int CommandId = 256;

        /// <summary>
        /// Command menu group (command set GUID).
        /// </summary>
        public static readonly Guid CommandSet = new Guid("e55640c4-cab7-4cc6-9ab1-d949f8b90bfb");

        /// <summary>
        /// VS Package that provides this command, not null.
        /// </summary>
        private readonly AsyncPackage package;

        private static DTE2 _dte;

        /// <summary>
        /// Initializes a new instance of the <see cref="MainCommand"/> class.
        /// Adds our command handlers for menu (commands must exist in the command table file)
        /// </summary>
        /// <param name="package">Owner package, not null.</param>
        /// <param name="commandService">Command service to add command to, not null.</param>
        private MainCommand(AsyncPackage package, OleMenuCommandService commandService)
        {
            this.package = package ?? throw new ArgumentNullException(nameof(package));
            commandService = commandService ?? throw new ArgumentNullException(nameof(commandService));

            var menuCommandID = new CommandID(CommandSet, CommandId);
            var menuItem = new MenuCommand(this.Execute, menuCommandID);
            commandService.AddCommand(menuItem);
        }

        /// <summary>
        /// Gets the instance of the command.
        /// </summary>
        public static MainCommand Instance
        {
            get;
            private set;
        }

        /// <summary>
        /// Gets the service provider from the owner package.
        /// </summary>
        private Microsoft.VisualStudio.Shell.IAsyncServiceProvider ServiceProvider
        {
            get
            {
                return this.package;
            }
        }

        /// <summary>
        /// Initializes the singleton instance of the command.
        /// </summary>
        /// <param name="package">Owner package, not null.</param>
        public static async Task InitializeAsync(AsyncPackage package, DTE2 dte)
        {
            // Switch to the main thread - the call to AddCommand in MainCommand's constructor requires
            // the UI thread.
            await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(package.DisposalToken);

            _dte = dte;

            OleMenuCommandService commandService = await package.GetServiceAsync(typeof(IMenuCommandService)) as OleMenuCommandService;
            Instance = new MainCommand(package, commandService);
        }

        /// <summary>
        /// This function is the callback used to execute the command when the menu item is clicked.
        /// See the constructor to see how the menu item is associated with this function using
        /// OleMenuCommandService service and MenuCommand class.
        /// </summary>
        /// <param name="sender">Event sender.</param>
        /// <param name="e">Event args.</param>
        private void Execute(object sender, EventArgs e)
        {
            ThreadHelper.ThrowIfNotOnUIThread();
            //string message = string.Format(CultureInfo.CurrentCulture, "Inside {0}.MenuItemCallback()", this.GetType().FullName);
            //string title = "MainCommand";

            // Show a message box to prove we were here
            //VsShellUtilities.ShowMessageBox(
            //    this.package,
            //    message,
            //    title,
            //    OLEMSGICON.OLEMSGICON_INFO,
            //    OLEMSGBUTTON.OLEMSGBUTTON_OK,
            //    OLEMSGDEFBUTTON.OLEMSGDEFBUTTON_FIRST);
            //var (path, srcPath, name) = GetProjectPath(this.package);

            MainForm mainForm = new MainForm(_dte);
            mainForm.Show();
        }

        private static void ShowMessage(string msg, IServiceProvider serviceProvider)
        {
            VsShellUtilities.ShowMessageBox(
               serviceProvider,
               msg,
               "提示",
               OLEMSGICON.OLEMSGICON_INFO,
               OLEMSGBUTTON.OLEMSGBUTTON_OK,
               OLEMSGDEFBUTTON.OLEMSGDEFBUTTON_FIRST);
        }

        private static Tuple<string, string, string> GetFilePath(IServiceProvider serviceProvider)
        {
            ThreadHelper.ThrowIfNotOnUIThread();
            var dte = serviceProvider.GetService(typeof(DTE)) as DTE;
            //var selection = dte.ActiveDocument.Selection as TextSelection;//当前文档中选中的部分
            //if (selection == null)
            //{
            //    return string.Empty;
            //}
            return Tuple.Create(@"D:\VSIXDome\VSIXDome\Test\GoodsEntity.cs", @"D:\VSIXDome\VSIXDome\Test\", "GoodsEntity.cs");
        }

        private static Tuple<string, string, string> GetProjectPath(IServiceProvider serviceProvider)
        {
            ThreadHelper.ThrowIfNotOnUIThread();
            //var dte = serviceProvider.GetService(typeof(DTE)) as DTE2;

            // t.Text;
            var projects = (UIHierarchyItem[])_dte?.ToolWindows.SolutionExplorer.SelectedItems;

            //var command = new MainCommandBase();
            //var selectedItem = _dte.SelectedItems.Item(1);
            //ProjectItem selectProjectItem = selectedItem.ProjectItem;
            //var classCode = command.GetClass(selectProjectItem.FileCodeModel.CodeElements);
            //var name = classCode.Name;

            ////当前类命名空间
            //string namespaceStr = selectProjectItem.FileCodeModel.CodeElements.OfType<CodeNamespace>().First().FullName;
            ////当前项目根命名空间
            //string applicationStr = "";
            //if (!string.IsNullOrEmpty(namespaceStr))
            //{
            //    applicationStr = namespaceStr.Substring(0, namespaceStr.LastIndexOf("."));
            //}
            //var projName = selectProjectItem.ContainingProject.FullName;
            //var type = Type.GetType($"{namespaceStr}.{name}");
            //var classs = classCode.Bases as CodeElement;
            //foreach (var baseClass in classCode.Bases)
            //{
            //    var bClass = baseClass as CodeElement;
            //    var baseClassName = bClass.Name;
            //}

            if (projects == null)
            {
                ShowMessage("未选中任何项目!", serviceProvider);
                return null;

            }
            var project = projects[0];
            var item = project.Object as Project;
            var path = item?.FullName;
            if (string.IsNullOrWhiteSpace(path))
            {
                ShowMessage("项目路径为空!", serviceProvider);
                return null;

            }
            if (!File.Exists(path))
            {
                ShowMessage(path + "文件不存在!", serviceProvider);
                return null;

            }

            var srcPath = item?.Properties.Item("FullPath").Value?.ToString();
            if (string.IsNullOrWhiteSpace(srcPath))
            {
                ShowMessage("FullPath路径为空!", serviceProvider);
                return null;

            }

            //var command = new Command();
            //var selectedItem = _dte.SelectedItems.Item(1);
            //ProjectItem selectProjectItem = selectedItem.ProjectItem;
            //command.GetClass(selectProjectItem.FileCodeModel.CodeElements);

            //path:.csproj全路径
            //srcPath:.csproj所在的目录
            //item.Name:项目名称
            return Tuple.Create(path, srcPath, item.Name);
        }
    }
}
